package com.ruoyi.mall.wxpay;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.utils.uuid.UUID;
import com.ruoyi.mall.wxpay.vo.WXPayOrderReqVO;
import com.ruoyi.mall.wxpay.vo.WxPayRespVO;
import com.ruoyi.mall.wxpay.vo.WxPayV3Bean;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.wechat.pay.java.core.http.Constant.*;

@Service
public class WXPayService {
    @Autowired
    private WxPayV3Bean wxPayV3Bean;

    public WxPayRespVO createOrder(WXPayOrderReqVO req) throws Exception {
        try {
            // 使用自动更新平台证书的RSA配置
            // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
            Config config =
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(wxPayV3Bean.getMchId())
                            .privateKeyFromPath(wxPayV3Bean.getKeyPath())
                            .merchantSerialNumber(wxPayV3Bean.getMchSerialNo())
                            .apiV3Key(wxPayV3Bean.getApiKey())
                            .build();
            // 构建service
            JsapiService service = new JsapiService.Builder().config(config).build();
            // request.setXxx(val)设置所需参数，具体参数可见Request定义
            PrepayRequest request = new PrepayRequest();
            Amount amount = new Amount();
            amount.setTotal(req.getTotalPrice());
            request.setAmount(amount);
            request.setAppid(wxPayV3Bean.getAppId());
            request.setMchid(wxPayV3Bean.getMchId());
            request.setDescription(req.getGoodsName());
            request.setNotifyUrl(wxPayV3Bean.getNotifyUrl());
            request.setOutTradeNo(req.getOrderSn().toString());
            request.setAttach(req.getOrderType());
            Payer payer = new Payer();
            payer.setOpenid(req.getOpenId());
            request.setPayer(payer);
            // 调用下单方法，得到应答
            PrepayResponse response = service.prepay(request);
            WxPayRespVO vo = new WxPayRespVO();
            Long timeStamp = System.currentTimeMillis() / 1000;
            vo.setTimeStamp(timeStamp);
            String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
            vo.setNonceStr(substring);
            String signatureStr = Stream.of(wxPayV3Bean.getAppId(), String.valueOf(timeStamp), substring, "prepay_id=" + response.getPrepayId())
                    .collect(Collectors.joining("\n", "", "\n"));
            String sign = WXPayUtil.getSign(signatureStr, wxPayV3Bean.getKeyPath());
            vo.setPaySign(sign);
            vo.setPrepayId("prepay_id=" + response.getPrepayId());
            return vo;
        }catch (ServiceException e){
            JSONObject parse = JSONObject.parseObject(e.getResponseBody());
            throw new com.ruoyi.common.core.exception.ServiceException(parse.getString("message"));
        }catch (Exception e){
            throw new com.ruoyi.common.core.exception.ServiceException(e.toString());
        }
    }


    public void payNotify(HttpServletRequest request) {
        try {
            //读取请求体的信息
            ServletInputStream inputStream = request.getInputStream();
            StringBuffer stringBuffer = new StringBuffer();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String s;
            //读取回调请求体
            while ((s = bufferedReader.readLine()) != null) {
                stringBuffer.append(s);
            }
            String s1 = stringBuffer.toString();
            String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
            String nonce = request.getHeader(WECHAT_PAY_NONCE);
            String signType = request.getHeader("Wechatpay-Signature-Type");
            String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
            String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
            // 如果已经初始化了 RSAAutoCertificateConfig，可直接使用
            // 没有的话，则构造一个
            NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(wxPayV3Bean.getMchId())
                    .privateKeyFromPath(wxPayV3Bean.getKeyPath())
                    .merchantSerialNumber(wxPayV3Bean.getMchSerialNo())
                    .apiV3Key(wxPayV3Bean.getApiKey())
                    .build();
            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser(config);
            RequestParam requestParam=new RequestParam.Builder()
                    .serialNumber(serialNo)
                    .nonce(nonce)
                    .signature(signature)
                    .timestamp(timestamp)
                    // 若未设置signType，默认值为 WECHATPAY2-SHA256-RSA2048
                    .signType(signType)
                    .body(s1)
                    .build();
            Transaction parse = parser.parse(requestParam, Transaction.class);
            System.out.println("parse = " + parse);
        } catch (Exception e) {
            throw new com.ruoyi.common.core.exception.ServiceException(e.toString());
        }
    }
}
